/*
 * @Author: 晟松
 * @Date: 2022-02-25 19:03:34
 * @LastEditors: 晟松
 * @LastEditTime: 2022-03-09 13:58:22
 * @FilePath: \mini-vue3d:\Code\node\koa2\volunteer-service\src\main\web3js\web3.js
 * @Description: 主要是关于web3 即区块链的一些东西和操作
 */
const Web3 = require("web3");
const Contract = require("web3-eth-contract");
// import LoginABI from "@main/web3js/ABI/Login";

// contract是用来操作智能合约的
Contract.setProvider("http://localhost:7545");
// web3是用来操作区块链的
let web3 = new Web3("http://localhost:7545");

// 合约ABI
import {
    LoginABI,
    CommunityABI,
    GlobalMessageABI,
    GroupVolABI,
    MessageABI,
    ResidentABI,
    SchoolABI,
    StudentABI,
    UserABI,
    VolABI,
    StudentGroupVolABI,
} from "@main/web3js/ABI";
import testAbi from "@main/web3js/ABI/Test";

// 合约地址
let LoginContractAddress = "0x4B780BF2927D0278Dad94B7d8B79C99bBF5081c9";
let CommunityContractAddress = "0xDb5b8c41d2f72b46F6780B96b11A95e1fDCFD679";
let GlobalMessageContractAddress = "0x40ea89B18423DAEb943F2697D641b7C7e2CD6156";
let GroupVolContractAddress = "0x40fc91FDcF0619eF998a19c5959C96c4796b5b13";
let MessageContractAddress = "0x706DbaAc222576cd6d62c24B95480687a89F4769";
let ResidentContractAddress = "0x024141187155dd4C5a9DB58A1e0BB546A468b882";
let SchoolContractAddress = "0xBC4Ee8AcD020e0052f2855b448e3979633E564Fd";
let StudentContractAddress = "0x31398cc917F25F05D30CA6eC514f0f69074C5880";
let UserContractAddress = "0x9b5cac5a4D2A540D71Fa28C853099d32D8C7E990";
let VolContractAddress = "0x5e53E54114267c2869D5f6c8F9Bab2550f98C6e9";

let StudentGroupVolContractAddress = "0x0a01a13729ed8ea5ee46730E1b4Db47Dc2291Bd6";

let testContractAddress = "0xd951ca45162aE4720E2C404273fDcEa23326A4c7";

let address = [];
(async function () {
    // ganache的所有用户地址
    address = await web3.eth.getAccounts();
    // 取第一个用户
    web3.eth.defaultAccount = address[0];
})();
// console.log("web3.eth.defaultAccount: ", web3.eth.defaultAccount);

/**
 * @description: 通过一个transactionHash，获取这个交易里面传输的数据
 * @param {*} transactionHash
 * @return {*}
 */
export async function getDataTxHash(transactionHash) {
    let tx = await web3.eth.getTransaction(transactionHash);

    let strObj = Buffer.from(tx.input.replace("0x", ""), "hex").toString();

    // 注意里面的tx.input是这个交易传输的数据，是默认转为了'0x278759cd00'这种格式，所以需要再转一下
    console.log("tx: ", tx, strObj, JSON.parse(strObj));
    return JSON.parse(strObj);
}

/**
 * @description: 获取一个块的hash的数据
 * @param {*} blockHash
 * @return {*}
 */
export async function getDataBlockHash(blockHash) {
    return await web3.eth.getTransaction(blockHash);
}

/**
 * @description: 处理login.sol的一些操作，主要通过一个交易擦魂帝数据，然后得到这个交易hash和块hash，就相当于将数据存上去了
 * @param {*} loginInfo 传来的login对象
 * @return {*}
 */
export async function remixLogin(loginInfo) {
    //创建智能合约，参数为solc编译后生成的abi
    let contract = new Contract(LoginABI, LoginContractAddress);

    // 转为字符串，因为只能合约里面是使用的字符串定义
    let data = JSON.stringify(loginInfo);
    console.log("data: ", data);
    // 调用智能合约的发送方法,注意是使用的send方法，且send里面还需要包括from，即发起者的地址
    // 注意里面的setLogin是自己写的sol代码里面的方法,可以再abi里面看见
    let res = await contract.methods.setLogin(data).send({
        from: address[0],
        gas: 2000000, //这里的gas是指传输这个数据最大为多少，所以也可相当于在这之下的都可以传
    });
    console.log("res更新: ", res);
    // 注意在这里需要存一下对应的transactionHash，方便后面去获取这一次传输的数据
    let { transactionHash, blockHash } = res;
    // 返回这两个hash值
    return { transactionHash, blockHash };

    // 获取数据，注意这里就是使用的call方法进行的一个获取的调用
    res = await contract.methods.getLogin().call({
        from: address[0],
        gas: 2000000,
    });

    console.log("res获取: ", res);
    // 获取这个交易的信息
    let tx = await web3.eth.getTransaction(transactionHash);
    // 注意里面的tx.input是这个交易传输的数据，是默认转为了'0x278759cd00'这种格式，所以需要再转一下
    console.log("tx: ", tx, Buffer.from(tx.input.replace("0x", ""), "hex").toString());

    // 获取这个块的信息
    let block = await web3.eth.getBlock(blockHash);
    console.log("block: ", block);
}
// remixLogin("jcs-蒋晟松");

export async function remixLoginStruct(loginStructInfo) {
    // 获取用户地址
    let address = await web3.eth.getAccounts();
    web3.eth.defaultAccount = address[0]; //创建智能合约，参数为solc编译后生成的abi
    console.log("web3.eth.defaultAccount: ", web3.eth.defaultAccount);

    // let Contract = web3.eth.contract(loginAbi);

    let contract = new Contract(testAbi, testContractAddress);

    // console.log("contract: ", contract);

    // 转为字符串，因为只能合约里面是使用的字符串定义
    // let data = JSON.stringify(loginInfo);
    // console.log("data: ", data);
    // 调用智能合约的发送方法,注意是使用的send方法，且send里面还需要包括from，即发起者的地址
    // 注意里面的setLogin是自己写的sol代码里面的方法,可以再abi里面看见
    let res = await contract.methods.setLoginStruct(loginStructInfo).send({
        from: address[0],
        gas: 2000000,
    });
    console.log("res更新: ", res);
    // 注意在这里需要存一下对应的transactionHash，方便后面去获取这一次传输的数据
    let { transactionHash, blockHash } = res;

    // 获取数据，注意这里就是使用的call方法进行的一个获取的调用
    res = await contract.methods.getLoginStruct().call({
        from: address[0],
        gas: 2000000,
    });

    console.log("res获取: ", res);
    // 获取这个交易的信息
    let tx = await web3.eth.getTransaction(transactionHash);
    // 注意里面的tx.input是这个交易传输的数据，是默认转为了'0x278759cd00'这种格式，所以需要再转一下
    console.log("tx: ", tx, Buffer.from(tx.input.replace("0x", ""), "hex").toString());

    // 获取这个块的信息
    let block = await web3.eth.getBlock(blockHash);
    console.log("block: ", block);
}
// 注意在solidity的struct里面传输数据时，需要使用这样的一个数组进行操作
// remixLoginStruct(["2132", "4423", 8])[("jcs", "蒋晟松", 78)];

/**
 * @description: 处理Community.sol的一些操作，主要通过一个交易存储数据，然后得到这个交易hash和块hash，就相当于将数据存上去了
 * @param {*} CommunityInfo 传来的Community对象
 * @return {*}
 */
export async function remixCommunity(CommunityInfo) {
    //创建智能合约，参数为solc编译后生成的abi
    let contract = new Contract(CommunityABI, CommunityContractAddress);

    // 转为字符串，因为只能合约里面是使用的字符串定义
    let data = JSON.stringify(CommunityInfo);
    console.log("data: ", data);
    // 调用智能合约的发送方法,注意是使用的send方法，且send里面还需要包括from，即发起者的地址
    // 注意里面的setCommunity是自己写的sol代码里面的方法,可以再abi里面看见
    let res = await contract.methods.setCommunity(data).send({
        from: address[0],
        gas: 2000000,
    });
    console.log("res更新: ", res);
    // 注意在这里需要存一下对应的transactionHash，方便后面去获取这一次传输的数据
    let { transactionHash, blockHash } = res;
    // 返回这两个hash值
    return { transactionHash, blockHash };
}

export async function remixGlobalMessage(GlobalMessageInfo) {
    //创建智能合约，参数为solc编译后生成的abi
    let contract = new Contract(GlobalMessageABI, GlobalMessageContractAddress);

    // 转为字符串，因为只能合约里面是使用的字符串定义
    let data = JSON.stringify(GlobalMessageInfo);
    console.log("data: ", data);
    // 调用智能合约的发送方法,注意是使用的send方法，且send里面还需要包括from，即发起者的地址
    // 注意里面的setGlobalMessage是自己写的sol代码里面的方法,可以再abi里面看见
    let res = await contract.methods.setGlobalMessage(data).send({
        from: address[0],
        gas: 2000000,
    });
    console.log("res更新: ", res);
    // 注意在这里需要存一下对应的transactionHash，方便后面去获取这一次传输的数据
    let { transactionHash, blockHash } = res;
    // 返回这两个hash值
    return { transactionHash, blockHash };
}

export async function remixGroupVol(GroupVolInfo) {
    //创建智能合约，参数为solc编译后生成的abi
    let contract = new Contract(GroupVolABI, GroupVolContractAddress);

    // 转为字符串，因为只能合约里面是使用的字符串定义
    let data = JSON.stringify(GroupVolInfo);
    console.log("data: ", data);
    // 调用智能合约的发送方法,注意是使用的send方法，且send里面还需要包括from，即发起者的地址
    // 注意里面的setGroupVol是自己写的sol代码里面的方法,可以再abi里面看见
    let res = await contract.methods.setGroupVol(data).send({
        from: address[0],
        gas: 2000000,
    });
    console.log("res更新: ", res);
    // 注意在这里需要存一下对应的transactionHash，方便后面去获取这一次传输的数据
    let { transactionHash, blockHash } = res;
    // 返回这两个hash值
    return { transactionHash, blockHash };
}

export async function remixMessage(MessageInfo) {
    //创建智能合约，参数为solc编译后生成的abi
    let contract = new Contract(MessageABI, MessageContractAddress);

    // 转为字符串，因为只能合约里面是使用的字符串定义
    let data = JSON.stringify(MessageInfo);
    console.log("data: ", data);
    // 调用智能合约的发送方法,注意是使用的send方法，且send里面还需要包括from，即发起者的地址
    // 注意里面的setMessage是自己写的sol代码里面的方法,可以再abi里面看见
    let res = await contract.methods.setMessage(data).send({
        from: address[0],
        gas: 2000000,
    });
    console.log("res更新: ", res);
    // 注意在这里需要存一下对应的transactionHash，方便后面去获取这一次传输的数据
    let { transactionHash, blockHash } = res;
    // 返回这两个hash值
    return { transactionHash, blockHash };
}

export async function remixResident(ResidentInfo) {
    //创建智能合约，参数为solc编译后生成的abi
    let contract = new Contract(ResidentABI, ResidentContractAddress);

    // 转为字符串，因为只能合约里面是使用的字符串定义
    let data = JSON.stringify(ResidentInfo);
    console.log("data: ", data);
    // 调用智能合约的发送方法,注意是使用的send方法，且send里面还需要包括from，即发起者的地址
    // 注意里面的setResident是自己写的sol代码里面的方法,可以再abi里面看见
    let res = await contract.methods.setResident(data).send({
        from: address[0],
        gas: 2000000,
    });
    console.log("res更新: ", res);
    // 注意在这里需要存一下对应的transactionHash，方便后面去获取这一次传输的数据
    let { transactionHash, blockHash } = res;
    // 返回这两个hash值
    return { transactionHash, blockHash };
}

export async function remixSchool(SchoolInfo) {
    //创建智能合约，参数为solc编译后生成的abi
    let contract = new Contract(SchoolABI, SchoolContractAddress);

    // 转为字符串，因为只能合约里面是使用的字符串定义
    let data = JSON.stringify(SchoolInfo);
    console.log("data: ", data);
    // 调用智能合约的发送方法,注意是使用的send方法，且send里面还需要包括from，即发起者的地址
    // 注意里面的setSchool是自己写的sol代码里面的方法,可以再abi里面看见
    let res = await contract.methods.setSchool(data).send({
        from: address[0],
        gas: 2000000,
    });
    console.log("res更新: ", res);
    // 注意在这里需要存一下对应的transactionHash，方便后面去获取这一次传输的数据
    let { transactionHash, blockHash } = res;
    // 返回这两个hash值
    return { transactionHash, blockHash };
}

export async function remixStudent(StudentInfo) {
    //创建智能合约，参数为solc编译后生成的abi
    let contract = new Contract(StudentABI, StudentContractAddress);

    // 转为字符串，因为只能合约里面是使用的字符串定义
    let data = JSON.stringify(StudentInfo);
    console.log("data: ", data);
    // 调用智能合约的发送方法,注意是使用的send方法，且send里面还需要包括from，即发起者的地址
    // 注意里面的setStudent是自己写的sol代码里面的方法,可以再abi里面看见
    let res = await contract.methods.setStudent(data).send({
        from: address[0],
        gas: 2000000,
    });
    console.log("res更新: ", res);
    // 注意在这里需要存一下对应的transactionHash，方便后面去获取这一次传输的数据
    let { transactionHash, blockHash } = res;
    // 返回这两个hash值
    return { transactionHash, blockHash };
}
export async function remixUser(UserInfo) {
    //创建智能合约，参数为solc编译后生成的abi
    let contract = new Contract(UserABI, UserContractAddress);

    // 转为字符串，因为只能合约里面是使用的字符串定义
    let data = JSON.stringify(UserInfo);
    console.log("data: ", data);
    // 调用智能合约的发送方法,注意是使用的send方法，且send里面还需要包括from，即发起者的地址
    // 注意里面的setUser是自己写的sol代码里面的方法,可以再abi里面看见
    let res = await contract.methods.setUser(data).send({
        from: address[0],
        gas: 2000000,
    });
    console.log("res更新: ", res);
    // 注意在这里需要存一下对应的transactionHash，方便后面去获取这一次传输的数据
    let { transactionHash, blockHash } = res;
    // 返回这两个hash值
    return { transactionHash, blockHash };
}

export async function remixVol(VolInfo) {
    //创建智能合约，参数为solc编译后生成的abi
    let contract = new Contract(VolABI, VolContractAddress);

    // 转为字符串，因为只能合约里面是使用的字符串定义
    let data = JSON.stringify(VolInfo);
    console.log("data: ", data);
    // 调用智能合约的发送方法,注意是使用的send方法，且send里面还需要包括from，即发起者的地址
    // 注意里面的setVol是自己写的sol代码里面的方法,可以再abi里面看见
    let res = await contract.methods.setVol(data).send({
        from: address[0],
        gas: 2000000,
    });
    console.log("res更新: ", res);
    // 注意在这里需要存一下对应的transactionHash，方便后面去获取这一次传输的数据
    let { transactionHash, blockHash } = res;
    // 返回这两个hash值
    return { transactionHash, blockHash };
}

export async function remixStudentGroupVol(StudentGroupVol) {
    //创建智能合约，参数为solc编译后生成的abi
    let contract = new Contract(StudentGroupVolABI, StudentGroupVolContractAddress);

    // 转为字符串，因为只能合约里面是使用的字符串定义
    let data = JSON.stringify(StudentGroupVol);
    console.log("data: ", data);
    // 调用智能合约的发送方法,注意是使用的send方法，且send里面还需要包括from，即发起者的地址
    // 注意里面的setVol是自己写的sol代码里面的方法,可以再abi里面看见
    let res = await contract.methods.setStudentGroupVolItem(data).send({
        from: address[0],
        gas: 2000000,
    });
    console.log("res更新: ", res);
    // 注意在这里需要存一下对应的transactionHash，方便后面去获取这一次传输的数据
    let { transactionHash, blockHash } = res;
    // 返回这两个hash值
    return { transactionHash, blockHash };
}

export default {
    remixCommunity,
    remixGlobalMessage,
    remixGroupVol,
    remixLogin,
    remixMessage,
    remixResident,
    remixSchool,
    remixStudent,
    remixUser,
    remixVol,
    remixStudentGroupVol,
};
